// Logger (抽象基类)
// ├── SyncLogger (同步日志器)
// ├── AsyncLogger (异步日志器)
// └── Builder (建造者)
//     └── LocalLoggerBuilder (具体建造者)

#ifndef M_LOGGER_H__
#define M_LOGGER_H__

#include "utils.hpp"          // 工具函数
#include "levels.hpp"         // 日志级别定义
#include "message.hpp"       // 日志消息结构
#include "format.hpp"        // 日志格式化器
#include "sink.hpp"          // 日志输出目标
#include "looper.hpp"
#include <mutex>
#include <vector>
#include <list>
#include <atomic>
#include <cstdarg>
#include <unordered_map>

namespace tclog{

    class Logger{
    public:
        enum class Type{
            LOGGER_SYNC=0,
            LOGGER_ASYNC
        };
        using ptr=std::shared_ptr<Logger>;

        //构造函数
        Logger(const std::string &name,Formatter::ptr formatter,
            std::vector<LogSink::ptr> &sinks,LogLevel::value level=LogLevel::value::DEBUG):
            _name(name),_formatter(formatter),_level(level),_sinks(sinks.begin(),sinks.end()){}

        std::string loggerName() { return _name; }

        LogLevel::value loggerLevel() { return _level; }

        void debug(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::DEBUG) == false) {
                return ;
            }
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::DEBUG, file, line, fmt, al);
            va_end(al);
        }
        void info(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::INFO) == false) return ;
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::INFO, file, line, fmt, al);
            va_end(al);
        }
        void warn(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::WARN) == false) return ;
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::WARN, file, line, fmt, al);
            va_end(al);
        }
        void error(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::ERROR) == false) return ;
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::ERROR, file, line, fmt, al);
            va_end(al);
        }
        void fatal(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::FATAL) == false) return ;
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::FATAL, file, line, fmt, al);
            va_end(al);
        }

    class Builder{
        public:
            using ptr=std::shared_ptr<Builder>;

            Builder(): _level(LogLevel::value::DEBUG),
                        _logger_type(Logger::Type::LOGGER_SYNC){}

            // 配置方法
            void buildLoggerName(const std::string &name){ _logger_name=name;}
            void buildLoggerLevel(LogLevel::value level){ _level=level;}
            void buildLoggerType(Logger::Type type){ _logger_type=type;}
            void buildFormatter(const std::string pattern){ _formatter=std::make_shared<Formatter>(pattern);}
            void buildFormatter(const Formatter::ptr &formatter){ _formatter=formatter;}

            // 模板方法 - 创建任意类型的Sink
            template<typename SinkType, typename ...Args>
            void buildSink(Args &&...args){
                auto sink=SinkFactory::create<SinkType>(std::forward<Args>(args)...);
                _sinks.push_back(sink);
            }
            
            virtual Logger::ptr build() = 0;  // 纯虚构建方法
            
            // 调试方法：获取sinks数量
            size_t getSinksCount() const { return _sinks.size(); }

        protected:
            Logger::Type _logger_type;
            std::string _logger_name;
            LogLevel::value _level;
            Formatter::ptr _formatter;
            std::vector<LogSink::ptr> _sinks;

    };


    protected:
        //日志级别判断
        bool shouldLog(LogLevel::value level){ return level>=_level;}

        void log(LogLevel::value level, const char *file, size_t line, const char *fmt, va_list al) {
            char *buf;
            std::string msg;

            // 使用vasprintf进行格式化（类似vsprintf但自动分配内存）
            int len = vasprintf(&buf, fmt, al);
            if (len < 0) {
                msg = "格式化日志消息失败！！";
            }else {
                msg.assign(buf, len); // 将格式化结果赋值给msg
                free(buf);   // 释放vasprintf分配的内存
            }
            //LogMsg(name, file, line, payload, level)
            //创建日志消息对象
            LogMsg lm(_name, file, line, std::move(msg), level);

            // 格式化输出
            std::stringstream ss;
            _formatter->format(ss, lm);

            // 调用具体的输出实现
            logIt(std::move(ss.str()));
        }

        virtual void logIt(const std::string &msg) = 0;
    
    protected:
        std::mutex _mutex;                    // 线程安全
        std::string _name;                    // 日志器名称
        Formatter::ptr _formatter;            // 格式化器
        std::atomic<LogLevel::value> _level;  // 原子级别             
        std::vector<LogSink::ptr> _sinks;     // 输出目标集合

    };


class SyncLogger:public Logger{
        public:
            using ptr=std::shared_ptr<SyncLogger>;
        
            //构造函数
            SyncLogger(const std::string &name,Formatter::ptr formatter,
            std::vector<LogSink::ptr> &sinks,LogLevel::value level=LogLevel::value::DEBUG):
            Logger(name, formatter, sinks, level){
                std::cout << LogLevel::toString(level) << " 同步日志器: " << name << "创建成功...\n";
            }

        private:
            // 实现基类的纯虚函数 - 同步输出
            virtual void logIt(const std::string &msg){
                std::unique_lock<std::mutex> lock(_mutex);
                if (_sinks.empty()) { return ; }
                for(auto &sink:_sinks){
                    sink->log(msg.c_str(),msg.size());  //调用每个sink的输出
                }
            }
};

//异步日志器
class AsyncLogger : public Logger {
    public:
        using ptr = std::shared_ptr<AsyncLogger>;

        AsyncLogger(const std::string &name, 
            Formatter::ptr formatter, 
            std::vector<LogSink::ptr> &sinks, 
            LogLevel::value level = LogLevel::value::DEBUG): 
            Logger(name, formatter, sinks, level),
            _looper(std::make_shared<AsyncLooper>(std::bind(&AsyncLogger::backendLogIt, this, std::placeholders::_1))) {
            std::cout << LogLevel::toString(level) << "异步日志器: " << name << "创建成功...\n";
        }
        
// 这行代码创建了一个可调用对象，它等价于：
// [this](Buffer &buffer) { this->backendLogIt(buffer); }

//  std::bind 在这里起到了一个“函数适配器”的作用，它做了三件重要的事情：
// a) 绑定成员函数
// &AsyncLogger::backendLogIt 是一个成员函数指针。成员函数和普通函数不同，它隐藏了一个 this 参数（指向对象实例）。不能直接把它当普通函数用。

// b) 绑定对象实例 (this)
// this 指向当前正在构造的 AsyncLogger 对象。std::bind 将成员函数和它所要操作的对象实例绑定在一起。

// c) 预留参数位置 (std::placeholders::_1)
// std::placeholders::_1 表示：“当调用这个被绑定后的对象时，传入的第一个参数，应该放在我这里”。
    protected:
        //将格式化后的日志消息放入异步缓冲区中
        virtual void logIt(const std::string &msg) {
            _looper->push(msg);
        }
        //异步工作线程的回调函数
        void backendLogIt(Buffer &msg) {
            if (_sinks.empty()) { return; }
            for (auto &it : _sinks) {
                it->log(msg.begin(), msg.readAbleSize());
            }
        }
    protected:
        AsyncLooper::ptr _looper;
};


class LocalLoggerBuilder:public Logger::Builder{
    public:
        virtual Logger::ptr build(){
            if(_logger_name.empty()){
                std::cout<<"日志器名称不能为空！";
                abort();
            }
            if (_formatter.get() == nullptr) {
                std::cout << "当前日志器：" << _logger_name << " 未检测到日志格式，默认设置为[ %d{%H:%M:%S}%T%t%T[%p]%T[%c]%T%f:%l%T%m%n ]!\n";
                _formatter = std::make_shared<Formatter>();
            }
            if (_sinks.empty()) {
                std::cout << "当前日志器：" << _logger_name << " 未检测到落地方向，默认设置为标准输出!\n";
                _sinks.push_back(std::make_shared<StdoutSink>());
            }

            Logger::ptr lp;
            if (_logger_type == Logger::Type::LOGGER_ASYNC) {
                lp = std::make_shared<AsyncLogger>(_logger_name, _formatter, _sinks, _level);
            }else {
                lp = std::make_shared<SyncLogger>(_logger_name, _formatter, _sinks, _level);
            }
            return lp;
        }
};


//日志管理器（单例模式）
//全局访问点 ：提供统一的日志器管理入口
class loggerManager{
    private:
        std::mutex _mutex;
        Logger::ptr _root_logger;
        //注册表，存放所有创建的日志器
        std::unordered_map<std::string, Logger::ptr> _loggers;
    private:
        loggerManager(){ 
            std::unique_ptr<LocalLoggerBuilder> slb(new LocalLoggerBuilder());
            slb->buildLoggerName("root");
            slb->buildLoggerType(Logger::Type::LOGGER_SYNC);
            _root_logger = slb->build();
            _loggers.insert(std::make_pair("root", _root_logger));
        }
        loggerManager(const loggerManager&) = delete;
        loggerManager &operator=(const loggerManager&) = delete;

    public:
        static loggerManager& getInstance() {
            static loggerManager lm;
            return lm;
        }

        //日志器查询
        bool hasLogger(const std::string &name)  {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _loggers.find(name);
            if (it == _loggers.end()) {
                return false;
            }
            return true;
        }

        //日志器注册
        void addLogger(const std::string &name, const Logger::ptr logger) {
            std::unique_lock<std::mutex> lock(_mutex);
            _loggers.insert(std::make_pair(name, logger));
        }

        //日志器获取
        Logger::ptr getLogger(const std::string &name) {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _loggers.find(name);
            if (it == _loggers.end()) {
                return Logger::ptr(); // 返回空指针
            }
            return it->second;
        }
        //获取根日志器
        Logger::ptr rootLogger() {
            std::unique_lock<std::mutex> lock(_mutex);
            return _root_logger;
        }

};

// - LocalLoggerBuilder ：只返回日志器，不注册
// - GlobalLoggerBuilder ：创建后自动注册到全局管理器
class GlobalLoggerBuilder: public Logger::Builder {
    public:
        virtual Logger::ptr build() {
            if (_logger_name.empty()) {
                std::cout << "日志器名称不能为空！";
                abort();
            }
            assert(loggerManager::getInstance().hasLogger(_logger_name) == false);
            if (_formatter.get() == nullptr) {
                std::cout << "当前日志器：" << _logger_name << " 未检测到日志格式，默认设置为[ %d{%H:%M:%S}%T%t%T[%p]%T[%c]%T%f:%l%T%m%n ]!\n";
                _formatter = std::make_shared<Formatter>();
            }
            if (_sinks.empty()) {
                std::cout << "当前日志器：" << _logger_name << " 未检测到落地方向，默认设置为标准输出!\n";
                _sinks.push_back(std::make_shared<StdoutSink>());
            }
            Logger::ptr lp;
            if (_logger_type == Logger::Type::LOGGER_ASYNC) {
                lp = std::make_shared<AsyncLogger>(_logger_name, _formatter, _sinks, _level);
            }else {
                lp = std::make_shared<SyncLogger>(_logger_name, _formatter, _sinks, _level);
            }
            //注册到日志管理器中
            loggerManager::getInstance().addLogger(_logger_name, lp);
            return lp;
        }
};


}

#endif
